package com.library.admin.config;

import com.library.admin.filter.JwtAuthenticationTokenFilter;
import com.library.admin.handle.CustomAccessDeniedHandler;
import com.library.admin.handle.CustomAuthenticationEntryPoint;
import com.library.admin.handle.CustomAuthorizationManager;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * Spring Security配置
 *
 * @author: xyh
 * @create: 2023-10-03
 **/
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Resource
    private CustomAccessDeniedHandler customAccessDeniedHandler;
    @Resource
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Resource
    private RequestMatcher[] requestMatchers;
    @Resource
    private CustomAuthorizationManager customAuthorizationManager;
    @Resource
    private AuthenticationProvider authenticationProvider;


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // CSRF禁用，因为不使用session
                .csrf(csrf -> csrf.disable())
                // 路径配置
                .authorizeHttpRequests(register -> register
                        .requestMatchers(requestMatchers).permitAll()
                        .anyRequest().access(customAuthorizationManager)
                )
                .formLogin(f -> f.disable())
                // 禁用缓存
                .sessionManagement(s ->
                        // 使用无状态session，即不使用session缓存数据
                        s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationProvider(authenticationProvider)
                // 添加JWT过滤器
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                // 权限不足时的处理
                .exceptionHandling(e -> e
                                .authenticationEntryPoint(customAuthenticationEntryPoint)
                                .accessDeniedHandler(customAccessDeniedHandler)
                );
        return http.build();
    }
}
